package pv.finder;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;

import pv.dao.CategoryDAO;
import pv.dao.DistrictDAO;
import pv.dao.PlaceDAO;
import pv.dao.ProvinceDAO;
import pv.dao.SQLiteHelper;
import pv.dao.SubCategoryDAO;
import pv.dao.WardDAO;
import pv.dto.AbstractDTO;
import pv.dto.CategoryDTO;
import pv.dto.DistrictDTO;
import pv.dto.PlaceDTO;
import pv.dto.ProvinceDTO;
import pv.dto.SubCategoryDTO;
import pv.dto.WardDTO;
import pv.finder.R;
import pv.network.BaseAsyncTask;
import pv.util.DataSearch;
import pv.util.Utility;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

public class DataHelper {

	static PlaceDTO[] places;
	static CategoryDTO[] categories;
	static SubCategoryDTO[] subcategorys;
	static WardDTO[] wards;
	static DistrictDTO[] districts;
	static ProvinceDTO[] provinces;

	public PlaceDTO[] getPlaces() {
		return places;
	}

	public CategoryDTO[] getCategories() {
		return categories;
	}

	public SubCategoryDTO[] getSubcategorys() {
		return subcategorys;
	}

	public WardDTO[] getWards() {
		return wards;
	}

	public DistrictDTO[] getDistricts() {
		return districts;
	}

	public ProvinceDTO[] getProvinces() {
		return provinces;
	}

	public LoadDataListener getListener() {
		return listener;
	}

	Context context;
	SQLiteHelper dbHelper;
	PlaceDAO placeDao;
	CategoryDAO categoryDao;
	SubCategoryDAO subcategoryDao;
	WardDAO wardDao;
	DistrictDAO districtDao;
	ProvinceDAO provinceDao;
	LoadDataListener listener;

	public DataHelper(Context context) {
		this.context = context;

		dbHelper = new SQLiteHelper(context);
		this.placeDao = new PlaceDAO(dbHelper);
		this.categoryDao = new CategoryDAO(dbHelper);
		this.subcategoryDao = new SubCategoryDAO(dbHelper);
		this.wardDao = new WardDAO(dbHelper);
		this.provinceDao = new ProvinceDAO(dbHelper);
		this.districtDao = new DistrictDAO(dbHelper);

		//
		categories = null;

	}

	public void setListener(LoadDataListener listener) {
		this.listener = listener;
	}

	public void loadData(DataSearch search) {
		new LoadDataPlace(context, search).execute("");
	}

	public void syncDataWithServer(DataSearch search) {
		if (!existsDatabase()) {
			new SyncDataFromServer(context, search).execute("");
		}
	}

	public void syncDataWithServer() {
		if (!existsDatabase()) {
			new SyncDataFromServer(context).execute("");
		}
	}

	public boolean existsDatabase() {
		// TODO Auto-generated method stub
		File database = context.getApplicationContext().getDatabasePath(
				SQLiteHelper.DATABASE_NAME);
		return database.exists();
	}

	public void getDataForAddress() {
		new LoadDataForAddress(context).execute("");
	}

	public WardDTO getWard(String name) {
		if (wards == null || wards.length == 0)
			return null;
		for (int i = 0; i < wards.length; i++) {
			if (name.equals(wards[i].getName())) {
				return wards[i];
			}
		}
		return null;
	}

	public DistrictDTO getDistrict(String name) {
		if (districts == null || districts.length == 0)
			return null;
		for (int i = 0; i < districts.length; i++) {
			if (name.equals(districts[i].getName())) {
				return districts[i];
			}
		}
		return null;
	}

	public ProvinceDTO getProvince(String name) {
		if (provinces == null || provinces.length == 0)
			return null;
		for (int i = 0; i < provinces.length; i++) {
			if (name.equals(provinces[i].getName())) {
				return provinces[i];
			}
		}
		return null;
	}

	public void init() {
		// TODO Auto-generated method stub
		if (existsDatabase()) {
			getDataForAddress();
		} else {
			syncDataWithServer();
		}
	}

	public class SyncDataFromServer extends BaseAsyncTask {

		DataSearch search = null;

		public SyncDataFromServer(Context context) {
			super(context);
			// TODO Auto-generated constructor stub

		}

		public SyncDataFromServer(Context context, DataSearch search) {
			super(context);
			// TODO Auto-generated constructor stub
			this.search = search;
		}

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();

		}

		@Override
		protected String doInBackground(String... urls) {
			// TODO Auto-generated method stub
			try {
				MyHttpMethod method = new MyHttpGetMethod(
						context.getString(R.string.url_get_data));
				method.setReadTimeOut(30000);
				String strJson = method.excute();

				JSONArray jarray = new JSONArray(strJson);
				List<Integer> category = new ArrayList<Integer>();
				List<Integer> subcategory = new ArrayList<Integer>();
				List<Integer> ward = new ArrayList<Integer>();
				List<Integer> district = new ArrayList<Integer>();
				List<Integer> province = new ArrayList<Integer>();

				SQLiteDatabase db = dbHelper.getWritableDatabase();

				Gson gson = new Gson();
				AbstractDTO dto;
				for (int i = 0; i < jarray.length(); i++) {
					if (!jarray.isNull(i)) {

						if (!jarray.getJSONObject(i).isNull("category")) {

							dto = gson.fromJson(jarray.getJSONObject(i)
									.getJSONObject("category").toString(),
									CategoryDTO.class);
							if (!category.contains(((CategoryDTO) dto).getId())) {
								categoryDao.insert(dto, db);
								category.add(((CategoryDTO) dto).getId());
							}

						}
						if (!jarray.getJSONObject(i).isNull("sub_category")) {
							dto = gson.fromJson(jarray.getJSONObject(i)
									.getJSONObject("sub_category").toString(),
									SubCategoryDTO.class);
							if (!subcategory.contains(((SubCategoryDTO) dto)
									.getId())) {
								subcategoryDao.insert(dto, db);
								subcategory.add(((SubCategoryDTO) dto).getId());
							}

						}
						if (!jarray.getJSONObject(i).isNull("ward")) {
							dto = gson.fromJson(jarray.getJSONObject(i)
									.getJSONObject("ward").toString(),
									WardDTO.class);

							if (!ward.contains(((WardDTO) dto).getId())) {
								wardDao.insert(dto, db);
								ward.add(((WardDTO) dto).getId());

							}
						}
						if (!jarray.getJSONObject(i).isNull("district")) {
							dto = gson.fromJson(jarray.getJSONObject(i)
									.getJSONObject("district").toString(),
									DistrictDTO.class);
							if (!district.contains(((DistrictDTO) dto).getId())) {
								districtDao.insert(dto, db);
								district.add(((DistrictDTO) dto).getId());
							}
						}
						if (!jarray.getJSONObject(i).isNull("province")) {
							dto = gson.fromJson(jarray.getJSONObject(i)
									.getJSONObject("province").toString(),
									ProvinceDTO.class);
							if (!province.contains(((ProvinceDTO) dto).getId())) {
								provinceDao.insert(dto, db);
								province.add(((ProvinceDTO) dto).getId());

							}
						}

						placeDao.insert(gson.fromJson(jarray.getJSONObject(i)
								.toString(), PlaceDTO.class), db);

					}
				}
				Utility.LogM(this.getClass(), String.valueOf(category.size()));
				Utility.LogM(this.getClass(),
						String.valueOf(subcategory.size()));
				Utility.LogM(this.getClass(), String.valueOf(ward.size()));
				Utility.LogM(this.getClass(), String.valueOf(district.size()));
				Utility.LogM(this.getClass(), String.valueOf(province.size()));

				db.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				Log.e(DataHelper.class.toString(), e.getMessage());
				return context.getString(R.string.TASK_ERROR_NETWORK);

			} catch (JSONException e) {
				// TODO Auto-generated catch block
				Log.e(DataHelper.class.toString(), e.getMessage());
				return context.getString(R.string.TASK_ERROR_COMMON);
			}
			return context.getString(R.string.TASK_SUCCESS);
		}

		@Override
		protected void doIfSuccess() {
			// TODO Auto-generated method stub
			if (search != null) {
				new LoadDataPlace(context, search).execute("");
			} else {
				Utility.showMessage(context,
						context.getString(R.string.sync_success));
			}

		}
	}

	public class LoadDataPlace extends BaseAsyncTask {

		DataSearch search;

		public LoadDataPlace(Context context, DataSearch search) {
			super(context);
			// TODO Auto-generated constructor stub
			this.search = search;
		}

		@Override
		protected String doInBackground(String... urls) {
			// TODO Auto-generated method stub
			// SQLiteDatabase db = dbHelper.getReadableDatabase();

			SQLiteDatabase db = dbHelper.getReadableDatabase();

			places = placeDao.getRows(search.getProjection(),
					search.getWhereColumn(), search.getWhereValue(),
					search.getSortOrder(), db);
			if (categories == null || categories.length == 0) {
				categories = categoryDao.getRows(db);
			}
			if (subcategorys == null || subcategorys.length == 0) {
				subcategorys = subcategoryDao.getRows(db);
			}
			if (wards == null || wards.length == 0) {
				wards = wardDao.getRows(db);
			}
			if (districts == null || districts.length == 0) {
				districts = districtDao.getRows(db);
			}
			if (provinces == null || provinces.length == 0) {
				provinces = provinceDao.getRows(db);
			}

			db.close();
			return context.getString(R.string.TASK_SUCCESS);
		}

		@Override
		protected void doIfSuccess() {
			// TODO Auto-generated method stub
			// if (places == null || places.isEmpty()) {

			// new SyncDataFromServer(context).execute("");
			// }
			if (places != null && (places.length > 0) && listener != null) {
				listener.callback(places);
			}

		}
	}

	public class LoadDataForAddress extends BaseAsyncTask {

		public LoadDataForAddress(Context context) {
			super(context);
			// TODO Auto-generated constructor stub
		}

		@Override
		protected String doInBackground(String... urls) {
			// TODO Auto-generated method stub
			// SQLiteDatabase db = dbHelper.getReadableDatabase();
			try {
				SQLiteDatabase db = dbHelper.getReadableDatabase();
				// for infomation of places
				districts = districtDao.getRows(db).clone();
				wards = wardDao.getRows(db).clone();
				provinces = provinceDao.getRows(db);
				// category
				categories = categoryDao.getRows(db);
				subcategorys = subcategoryDao.getRows(db);

				db.close();

			} catch (Exception e) {
				// TODO: handle exception

			}

			return context.getString(R.string.TASK_SUCCESS);
		}

		@Override
		protected void doIfSuccess() {
			// TODO Auto-generated method stub
			// if (places == null || places.isEmpty()) {
			// new SyncDataFromServer(context).execute("");
			// }
			if (districts != null && districts.length > 0 && districts != null) {
			}

		}
	}

	public interface LoadDataListener {
		public void callback(PlaceDTO[] places);
	}

	public void load() {
		new LoadDataForAddress(context).execute("");
	}

}
